package com.hgyc.mom.mes.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hgyc.mom.common.config.FileProperties;
import com.hgyc.mom.common.context.FileServiceContext;
import com.hgyc.mom.common.converter.ImageConverter;
import com.hgyc.mom.common.converter.ImageConverterFactory;
import com.hgyc.mom.common.exception.BizException;
import com.hgyc.mom.common.util.StringUtils;
import com.hgyc.mom.common.util.file.FileUtils;
import com.hgyc.mom.mes.entity.SopAttachment;
import com.hgyc.mom.mes.mapper.SopAttachmentMapper;
import com.hgyc.mom.mes.service.SopAttachmentService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;

/**
 * sop上传文件Service业务层实现
 *
 * @author fwj
 * @since 2025-06-18
 */
@Slf4j
@Service
public class SopAttachmentServiceImpl extends ServiceImpl<SopAttachmentMapper, SopAttachment> implements SopAttachmentService {

    @Autowired
    private FileServiceContext fileServiceContext;

    @Autowired
    private FileProperties fileProperties;

    @Override
    public List<SopAttachment> getByParent(Long parentId) {
        LambdaQueryWrapper<SopAttachment> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SopAttachment::getParentId, parentId);
        return list(queryWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeAttachment(Long id) {
        SopAttachment sopAttachment = getById(id);
        if (sopAttachment != null) {
            fileServiceContext.deleteFile(sopAttachment.getFileUrl());
        }

        List<SopAttachment> childrenAttachment = getByParent(id);
        if (!CollectionUtils.isEmpty(childrenAttachment)) {
            for (SopAttachment child : childrenAttachment) {
                fileServiceContext.deleteFile(child.getFileUrl());
                removeById(child.getId());
            }
        }

        removeById(id);
    }

    @Override
    public SopAttachment uploadFile(MultipartFile file) {
        //1. 附件上传
        String filePath = fileServiceContext.uploadFile(file, "sop");

        SopAttachment sopAttachment = new SopAttachment();
        sopAttachment.setFileName(file.getOriginalFilename());
        sopAttachment.setFileUrl(filePath);
        sopAttachment.setFileType(FileUtils.getExtension(file));
        sopAttachment.setStorage(fileProperties.getStrategy());
        sopAttachment.setFileSize(file.getSize());
        save(sopAttachment);

        //2. 在新线程中处理图片转换， 这里是独立的事务
        processFile(sopAttachment, file);

        return sopAttachment;
    }

    @Async
    @Transactional
    public void processFile(SopAttachment sopAttachment, MultipartFile file) {
        String fileType = sopAttachment.getFileType();
        if (!Arrays.asList("pdf", "pptx").contains(fileType)) {
            return;
        }

        ImageConverter imageConverter = ImageConverterFactory.getConverter(fileType);

        List<byte[]> imageBytes;
        try {
            imageBytes = imageConverter.convertToImages(file.getBytes());
        } catch (IOException exc) {
            log.error("转换图片失败：", exc);
            throw new RuntimeException(exc);
        }

        log.info("转换图片上传开始");

        for (int i = 0; i < imageBytes.size(); i++) {
            String fileName = this.getFileName(sopAttachment.getFileName()) + "page_" + i + ".png";

            log.info("上传图片{}开始", fileName);
            MockMultipartFile mockMultipartFile = new MockMultipartFile("file", fileName, "image/png", imageBytes.get(i));
            String filePath = fileServiceContext.uploadFile(mockMultipartFile, "sop");

            SopAttachment convertAttachment = new SopAttachment();
            convertAttachment.setParentId(sopAttachment.getId());
            convertAttachment.setFileName(fileName);
            convertAttachment.setFileUrl(filePath);
            convertAttachment.setFileType("png");
            convertAttachment.setStorage(fileProperties.getStrategy());
            convertAttachment.setPage(i);
            convertAttachment.setSerialNumber(i);

            super.save(convertAttachment); // 事务内提交

        }

        log.info("转换图片上传结束");
    }

    private String getFileName(String filename) {
        if (StringUtils.isEmpty(filename)) {
            return filename;
        }
        int dotIndex = filename.lastIndexOf('.');

        if (dotIndex == 0 && dotIndex == filename.length() - 1) {
            return filename;
        }
        return filename.substring(0, dotIndex).toLowerCase();
    }

    @Override
    public List<SopAttachment> getByParentId(Long id) {
        LambdaQueryWrapper<SopAttachment> qw = new LambdaQueryWrapper<SopAttachment>()
                .eq(SopAttachment::getParentId, id);
        return list(qw);
    }
}